#ifndef _ABCRYPTO_TYPES_H_
#define _ABCRYPTO_TYPES_H_

#include <stdint.h>
#include <stdbool.h>

#include "abcrypto_def.h"

/* Symmetric key cipher operations */
struct abcrypto_skcipher {
	int (*init_ctx)(void **ctx, uint8_t *key, uint32_t klen, uint8_t *iv,
			uint16_t alg, bool isenc);
	void (*free_ctx)(void *ctx);
	int (*encrypt)(void *ctx, uint8_t *iv, uint8_t *data, uint32_t len,
		       uint8_t *dst);
	int (*decrypt)(void *ctx, uint8_t *iv, uint8_t *data, uint32_t len,
		       uint8_t *dst);
	int (*once_encrypt)(uint8_t *key, uint8_t *iv, uint8_t *src,
			    uint8_t *dst, uint32_t len, uint16_t alg);
	int (*once_decrypt)(uint8_t *key, uint8_t *iv, uint8_t *src,
			    uint8_t *dst, uint32_t len, uint16_t alg);
};

struct abcrypto_auth {
	int (*init_ctx)(void **ctx, uint8_t *key, uint32_t klen, uint16_t alg);
	void (*free_ctx)(void *ctx);
	int (*update)(void *ctx, uint8_t *data, uint32_t len);
	int (*finish)(void *ctx, uint8_t *dgst);
	int (*digest)(uint8_t *data, uint32_t len, uint8_t *key, uint32_t klen,
		      uint8_t *dgst, uint16_t alg);
};

enum abcrypto_cipher_alg {
	ABCRYPTO_CIPHER_ALG_AES128 = 0,
	ABCRYPTO_CIPHER_ALG_AES192,
	ABCRYPTO_CIPHER_ALG_AES256,
	ABCRYPTO_CIPHER_ALG_SM4
};

enum abcrypto_cipher_mode {
	ABCRYPTO_CIPHER_MODE_ECB = 0,
	ABCRYPTO_CIPHER_MODE_CBC,
	ABCRYPTO_CIPHER_MODE_CTR,
	ABCRYPTO_CIPHER_MODE_CFB,
	ABCRYPTO_CIPHER_MODE_OFB,
};

enum abcrypto_auth_alg {
	ABCRYPTO_AUTH_ALG_MD5 = 0,
	ABCRYPTO_AUTH_ALG_SHA1,
	ABCRYPTO_AUTH_ALG_SHA224,
	ABCRYPTO_AUTH_ALG_SHA256,
	ABCRYPTO_AUTH_ALG_SHA384,
	ABCRYPTO_AUTH_ALG_SHA512,
	ABCRYPTO_AUTH_ALG_SHA3_224,
	ABCRYPTO_AUTH_ALG_SHA3_256,
	ABCRYPTO_AUTH_ALG_SHA3_384,
	ABCRYPTO_AUTH_ALG_SHA3_512,
	ABCRYPTO_AUTH_ALG_SM3,

};

enum abcrypto_auth_mode {
	ABCRYPTO_AUTH_MODE_HASH = 0,
	ABCRYPTO_AUTH_MODE_HMAC
};

enum abcrypto_alg {
	/*cipher*/
	/*aes128*/
	ABCRYPTO_CIPHER_AES_128_ECB = 0x0000,
	ABCRYPTO_CIPHER_AES_128_CBC = 0x0001,
	ABCRYPTO_CIPHER_AES_128_CTR = 0x0002,
	ABCRYPTO_CIPHER_AES_128_CFB = 0x0003,
	ABCRYPTO_CIPHER_AES_128_OFB = 0x0004,

	/*aes192*/
	ABCRYPTO_CIPHER_AES_192_ECB = 0x0010,
	ABCRYPTO_CIPHER_AES_192_CBC = 0x0011,
	ABCRYPTO_CIPHER_AES_192_CTR = 0x0012,
	ABCRYPTO_CIPHER_AES_192_CFB = 0x0013,
	ABCRYPTO_CIPHER_AES_192_OFB = 0x0014,

	/*aes256*/
	ABCRYPTO_CIPHER_AES_256_ECB = 0x0020,
	ABCRYPTO_CIPHER_AES_256_CBC = 0x0021,
	ABCRYPTO_CIPHER_AES_256_CTR = 0x0022,
	ABCRYPTO_CIPHER_AES_256_CFB = 0x0023,
	ABCRYPTO_CIPHER_AES_256_OFB = 0x0024,

	/*sm4*/
	ABCRYPTO_CIPHER_SM4_ECB = 0x0030,
	ABCRYPTO_CIPHER_SM4_CBC = 0x0031,
	ABCRYPTO_CIPHER_SM4_CTR = 0x0032,
	ABCRYPTO_CIPHER_SM4_CFB = 0x0033,
	ABCRYPTO_CIPHER_SM4_OFB = 0x0034,

	/*hash*/
	ABCRYPTO_HASH_MD5 = 0x0100,
	ABCRYPTO_HASH_SHA1 = 0x0101,
	ABCRYPTO_HASH_SHA224 = 0x0102,
	ABCRYPTO_HASH_SHA256 = 0x0103,
	ABCRYPTO_HASH_SHA384 = 0x0104,
	ABCRYPTO_HASH_SHA512 = 0x0105,
	ABCRYPTO_HASH_SHA3_224 = 0x0106,
	ABCRYPTO_HASH_SHA3_256 = 0x0107,
	ABCRYPTO_HASH_SHA3_384 = 0x0108,
	ABCRYPTO_HASH_SHA3_512 = 0x0109,
	ABCRYPTO_HASH_SM3 = 0x010a,

	/*hmac*/
	ABCRYPTO_HMAC_MD5 = 0x0110,
	ABCRYPTO_HMAC_SHA1 = 0x0111,
	ABCRYPTO_HMAC_SHA224 = 0x0112,
	ABCRYPTO_HMAC_SHA256 = 0x0113,
	ABCRYPTO_HMAC_SHA384 = 0x0114,
	ABCRYPTO_HMAC_SHA512 = 0x0115,
	ABCRYPTO_HMAC_SHA3_224 = 0x0116,
	ABCRYPTO_HMAC_SHA3_256 = 0x0117,
	ABCRYPTO_HMAC_SHA3_384 = 0x0118,
	ABCRYPTO_HMAC_SHA3_512 = 0x0119,
	ABCRYPTO_HMAC_SM3 = 0x011a,

	ABCRYPTO_RANDOM = 0x0200,

	ABCRYPTO_INVALID_ALG = 0xffff,
};

struct abcrypto_instance {
	char name[64];
	struct abcrypto_skcipher *(*get_skcipher)(uint16_t alg);
	struct abcrypto_auth *(*get_auth)(uint16_t alg);
};

#endif